#include "basic_board.h"

/**
 * @brief 配置事件指示灯管脚功能
 *
 */
static void EventLedPinConfiguration(void);

/**
 * @brief 配置警报指示灯管脚功能
 *
 */
static void AlarmLedPinConfiguration(void);

/**
 * @brief 设置事件指示灯为高电平
 *
 */
static void SetEventLedPinHightLevel(void);

/**
 * @brief 设置事件指示灯为低电平
 *
 */
static void SetEventLedPinLowLevel(void);

/**
 * @brief 设置警报指示灯为高电平
 *
 */
static void SetAlarmLedPinHightLevel(void);

/**
 * @brief 设置警报指示灯为低电平
 *
 */
static void SetAlarmLedPinLowLevel(void);

/**
 * @brief 设置事件指示灯管脚电平
 *
 * @param PinLevel - 管脚电平（true：高电平 false：低电平）
 */
static void SetEventLedPinLevel(bool PinLevel);

/**
 * @brief 设置警报指示灯管脚电平
 *
 * @param PinLevel - 管脚电平（true：高电平 false：低电平）
 */
static void SetAlarmLedPinLevel(bool PinLevel);

/**
 * @brief 关闭警报呼吸灯
 *
 */
static void CloseAlarmBreathingLight(void);

/**
 * @brief 更新警报呼吸灯输出占空比
 *
 * @param Cycle - 占空比
 */
static void UpdateAlarmBreathingLightDutyCycle(uint8_t Cycle);

static LedStatus_t EventLedStatus;      // 错误指示灯状态
static LedStatus_t ErrorLedStatus;      // 事件指示灯状态
static BreathingLight_t BreathingLight; // 呼吸灯

static void EventLedPinConfiguration(void)
{
#if _BOARD_TYPE_ == _6681_A_BOARD_
  GPIOB_ModeCfg(BASIC_EVENT_LED_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _6681_B_BOARD_
  GPIOB_ModeCfg(BASIC_EVENT_LED_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _M157_A_BOARD_
  GPIOB_ModeCfg(BASIC_EVENT_LED_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _9905_A_BOARD_
  GPIOB_ModeCfg(BASIC_EVENT_LED_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _9905_B_BOARD_
  GPIOB_ModeCfg(BASIC_EVENT_LED_PIN, GPIO_ModeOut_PP_20mA);
#endif

  SetEventLedPinLowLevel();
}

static void AlarmLedPinConfiguration(void)
{
#if _BOARD_TYPE_ == _6681_A_BOARD_
  GPIOB_ModeCfg(BASIC_ALARM_LED_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _6681_B_BOARD_
  GPIOA_ModeCfg(BASIC_ALARM_LED_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _M157_A_BOARD_
  GPIOA_ModeCfg(BASIC_ALARM_LED_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _9905_A_BOARD_
  GPIOB_ModeCfg(BASIC_ALARM_LED_PIN, GPIO_ModeOut_PP_20mA);

#elif _BOARD_TYPE_ == _9905_B_BOARD_
  GPIOB_ModeCfg(BASIC_ALARM_LED_PIN, GPIO_ModeOut_PP_20mA);
#endif

  SetAlarmLedPinLowLevel();
}

static void SetEventLedPinHightLevel(void)
{
#if _BOARD_TYPE_ == _6681_A_BOARD_
  GPIOB_SetBits(BASIC_EVENT_LED_PIN);

#elif _BOARD_TYPE_ == _6681_B_BOARD_
  GPIOB_SetBits(BASIC_EVENT_LED_PIN);

#elif _BOARD_TYPE_ == _M157_A_BOARD_
  GPIOB_SetBits(BASIC_EVENT_LED_PIN);

#elif _BOARD_TYPE_ == _9905_A_BOARD_
  GPIOB_SetBits(BASIC_EVENT_LED_PIN);

#elif _BOARD_TYPE_ == _9905_B_BOARD_
  GPIOB_SetBits(BASIC_EVENT_LED_PIN);
#endif
}

static void SetEventLedPinLowLevel(void)
{
#if _BOARD_TYPE_ == _6681_A_BOARD_
  GPIOB_ResetBits(BASIC_EVENT_LED_PIN);

#elif _BOARD_TYPE_ == _6681_B_BOARD_
  GPIOB_ResetBits(BASIC_EVENT_LED_PIN);

#elif _BOARD_TYPE_ == _M157_A_BOARD_
  GPIOB_ResetBits(BASIC_EVENT_LED_PIN);

#elif _BOARD_TYPE_ == _9905_A_BOARD_
  GPIOB_ResetBits(BASIC_EVENT_LED_PIN);

#elif _BOARD_TYPE_ == _9905_B_BOARD_
  GPIOB_ResetBits(BASIC_EVENT_LED_PIN);
#endif
}

static void SetAlarmLedPinHightLevel(void)
{
#if _BOARD_TYPE_ == _6681_A_BOARD_
  GPIOB_SetBits(BASIC_ALARM_LED_PIN);

#elif _BOARD_TYPE_ == _6681_B_BOARD_
  GPIOA_SetBits(BASIC_ALARM_LED_PIN);

#elif _BOARD_TYPE_ == _M157_A_BOARD_
  GPIOA_SetBits(BASIC_ALARM_LED_PIN);

#elif _BOARD_TYPE_ == _9905_A_BOARD_
  GPIOB_SetBits(BASIC_ALARM_LED_PIN);

#elif _BOARD_TYPE_ == _9905_B_BOARD_
  GPIOB_SetBits(BASIC_ALARM_LED_PIN);
#endif
}

static void SetAlarmLedPinLowLevel(void)
{
#if _BOARD_TYPE_ == _6681_A_BOARD_
  GPIOB_ResetBits(BASIC_ALARM_LED_PIN);

#elif _BOARD_TYPE_ == _6681_B_BOARD_
  GPIOA_ResetBits(BASIC_ALARM_LED_PIN);

#elif _BOARD_TYPE_ == _M157_A_BOARD_
  GPIOA_ResetBits(BASIC_ALARM_LED_PIN);

#elif _BOARD_TYPE_ == _9905_A_BOARD_
  GPIOB_ResetBits(BASIC_ALARM_LED_PIN);

#elif _BOARD_TYPE_ == _9905_B_BOARD_
  GPIOB_ResetBits(BASIC_ALARM_LED_PIN);
#endif
}

static void SetEventLedPinLevel(bool PinLevel)
{
  (PinLevel == true) ? SetEventLedPinHightLevel() : SetEventLedPinLowLevel();
}

static void SetAlarmLedPinLevel(bool PinLevel)
{
  (PinLevel == true) ? SetAlarmLedPinHightLevel() : SetAlarmLedPinLowLevel();
}

static void CloseAlarmBreathingLight(void)
{
#if _BOARD_TYPE_ == _6681_A_BOARD_
  GPIOPinRemap(DISABLE, RB_PIN_PWMX);
#endif

  R8_PWM_OUT_EN &= ~(BASIC_ALARM_BREATHING_LIGHT_CHANNEL);
}

static void UpdateAlarmBreathingLightDutyCycle(uint8_t Cycle)
{
#if _BOARD_TYPE_ == _6681_A_BOARD_
  GPIOPinRemap(ENABLE, RB_PIN_PWMX);
#endif

  PWMX_CLKCfg(87);
  PWMX_CycleCfg(PWMX_Cycle_255);

  uint8_t DutyCycle = (Cycle > 100) ? 100 : Cycle;
  PWMX_ACTOUT(BASIC_ALARM_BREATHING_LIGHT_CHANNEL, (uint8_t)((255 / 100.0) * DutyCycle), High_Level, ENABLE);
}

void PromptDeviceStartup(void)
{
  EventLedStatus.Status = LED_HINT_FLASHES;
  EventLedStatus.Mode = LED_HINT_STARTUP;
  EventLedStatus.Count = LED_FLASH_STARTUP_COUNT;
  BasicStartEventLedTaskNoWait();
}

void PromptDoorLockedRecovered(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void PromptDoorLockedTigger(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_LOCKED_TIGGER;
  ErrorLedStatus.Count = LED_FLASH_LOCKED_IN_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptOutOfValidityPeriod(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_TIME_ERROR;
  ErrorLedStatus.Count = LED_FLASH_NOT_IN_VALID_PERIOD_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptDoorLock(void)
{
  ErrorLedStatus.Count = 0;
  EventLedStatus.Mode = LED_HINT_IDLE;
  EventLedStatus.Status = LED_HINT_OFF;
  BasicStartEventLedTaskNoWait();
}

void PromptDoorUnlock(void)
{
  EventLedStatus.Mode = LED_HINT_UNLOCK;
  EventLedStatus.Status = LED_HINT_NORMAILON;
  BasicStartEventLedTaskNoWait();
}

void PromptAuthenticationError(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_INSUFFICIENT_PRIVILEGES;
  ErrorLedStatus.Count = LED_FLASH_AUTHENTICATION_ERROR_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptKeyHasBeenReplaced(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_CARD_REPLACE;
  ErrorLedStatus.Count = LED_FLASH_KEY_HAS_BEEN_REPLACED_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptDeviceIsInitializing(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_DEVICE_INITIALIZING;
  ErrorLedStatus.Count = LED_FLASH_SYSTEM_INITIALIZE_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptStartDeviceSelfTest(void)
{
  ErrorLedStatus.Status = LED_HINT_BREATHING_MODE;
  ErrorLedStatus.Mode = LED_HINT_DEVICE_SELF_TEST;
  BasicStartAlarmLedTaskNoWait();
}

void PromptExitDeviceSelfTest(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void PromptDeviceSelfTestError(uint8_t ErrorType)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_DECICE_SELF_TEST_ERROR;
  ErrorLedStatus.Count = LED_FLASH_DEVICE_SELF_TEST_ERROR_COUNT + ErrorType;
  BasicStartAlarmLedTaskNoWait();
}

void PromptFalseLockAlarmRecovered(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void PromptFalseLockTigger(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_FALSE_LOCK_TIGGER;
  ErrorLedStatus.Count = LED_FLASH_FALSE_LOCK_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptLowPower(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_LOW_POWER;
  ErrorLedStatus.Count = LED_FLASH_LOW_POWER_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptSetParameterError(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_SET_PARAMETER_ERROR;
  ErrorLedStatus.Count = LED_FLASH_SET_PARAMETER_ERROR_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptSetParameterSuccess(void)
{
  EventLedStatus.Status = LED_HINT_FLASHES;
  EventLedStatus.Mode = LED_HINT_SET_PARAMETER_SUCCESS;
  EventLedStatus.Count = LED_FLASH_SET_PARAMETER_SUCCESS_COUNT;
  BasicStartEventLedTaskNoWait();
}

void PromptSystemLocked(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_SYSTEM_LOCKED;
  ErrorLedStatus.Count = LED_FLASH_SYSTEM_LOCKED_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptStartLocalRegistration(void)
{
  EventLedStatus.Count = 0;
  EventLedStatus.Status = LED_HINT_NORMAILON;
  EventLedStatus.Mode = LED_HINT_START_LOCAL_REGISTER;
  BasicStartEventLedTaskNoWait();
}

void PromptExitLocalRegistration(void)
{
  EventLedStatus.Count = 0;
  EventLedStatus.Mode = LED_HINT_IDLE;
  EventLedStatus.Status = LED_HINT_OFF;
  BasicStartEventLedTaskNoWait();
}

void PromptKeyOperationError(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_KEY_OPERATION_ERROR;
  ErrorLedStatus.Count = LED_FLASH_KEY_OPERATION_ERROR_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptKeyOperationSuccess(void)
{
  EventLedStatus.Status = LED_HINT_FLASHES;
  EventLedStatus.Mode = LED_HINT_KEY_OPERATION_SUCCESS;
  ErrorLedStatus.Count = LED_FLASH_KEY_OPERATION_SUCCESS_COUNT;
  BasicStartEventLedTaskNoWait();
}

void PromptExitDeviceLockedState(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void PromptDeviceIsInLockedState(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_DEVICE_LOCKED_STATE;
  ErrorLedStatus.Count = LED_FLASH_DEVICE_LOCKED_STATUS_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptNetworkAttachmentEnd(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void PromptNetworkAttachmentStart(void)
{
  ErrorLedStatus.Status = LED_HINT_BREATHING_MODE;
  ErrorLedStatus.Mode = LED_HINT_NETWORK_ATTACHMENT_START;
  BasicStartAlarmLedTaskNoWait();
}

void PromptNetworkAttachmentSuccess(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void PromptNetworkAttachmentError(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_NETWORK_ATTACHMENT_ERROR;
  ErrorLedStatus.Count = LED_FLASH_NETWORK_ATTACHMENT_ERROR_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptAntiPickingRecovered(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void PromptAntiPickingAlarm(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_ANTI_BREAKING_ALARM_TIGGER;
  ErrorLedStatus.Count = LED_FLASH_ANTI_BREAKING_ALARM_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptUserKeyedKeys(void)
{
  EventLedStatus.Status = LED_HINT_NORMAILON;
  EventLedStatus.Mode = LED_HINT_USER_KEYED_KEYS;
  BasicStartEventLedTaskNoWait();
}

void PromptExitKeyEntry(void)
{
  EventLedStatus.Count = 0;
  EventLedStatus.Mode = LED_HINT_IDLE;
  EventLedStatus.Status = LED_HINT_OFF;
  BasicStartEventLedTaskNoWait();
}

void PromptHostConnectionLose(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_HOST_CONNECT_LOSE;
  ErrorLedStatus.Count = LED_FLASH_HOST_CONNECT_LOSE_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptConnectTest(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_CONNECT_TEST;
  ErrorLedStatus.Count = LED_FLASH_CONNECT_TEST_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptKeyRemove(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void PromptKeyInserted(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_KEY_INSERTED;
  ErrorLedStatus.Count = LED_FLASH_KEY_INSERTED_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptNormalOpenRecovered(void)
{
  EventLedStatus.Count = 0;
  EventLedStatus.Mode = LED_HINT_IDLE;
  EventLedStatus.Status = LED_HINT_OFF;
  BasicStartEventLedTaskNoWait();
}

void PromptNormalOpenTigger(void)
{
  EventLedStatus.Status = LED_HINT_FLASHES;
  EventLedStatus.Mode = LED_HINT_NORMAL_OPEN_TIGGER;
  EventLedStatus.Count = LED_FLASH_NORMAL_OPEN_COUNT;
  BasicStartEventLedTaskNoWait();
}

void PromptOnlineRegisterUser(void)
{
  ErrorLedStatus.Status = LED_HINT_BREATHING_MODE;
  ErrorLedStatus.Mode = LED_HINT_ONLINE_REGISTER_USER;
  BasicStartAlarmLedTaskNoWait();
}

void PromptExitOnlineRegisterUser(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void PromptExitSafetyModuleAuthentication(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void PromptStartSafetyModuleAuthentication(void)
{
  ErrorLedStatus.Status = LED_HINT_BREATHING_MODE;
  ErrorLedStatus.Mode = LED_HINT_START_SAFETY_MODULE_AUTHENTICATE;
  BasicStartAlarmLedTaskNoWait();
}

void PromptIntoStandby(void)
{
  ErrorLedStatus.Status = LED_HINT_FLASHES;
  ErrorLedStatus.Mode = LED_HINT_DEVICE_INTO_STANDBY_MODE;
  ErrorLedStatus.Count = LED_FLASH_DEVICE_INTO_STANDBY_MODE_COUNT;
  BasicStartAlarmLedTaskNoWait();
}

void PromptExitStandbyMode(void)
{
  ErrorLedStatus.Count = 0;
  ErrorLedStatus.Mode = LED_HINT_IDLE;
  ErrorLedStatus.Status = LED_HINT_OFF;
  BasicStartAlarmLedTaskNoWait();
}

void StopAllLightAlerts(void)
{
  BasicStopEventLedTask();
  BasicStopAlarmLedTask();

  memset(&EventLedStatus, 0, sizeof(LedStatus_t));
  memset(&ErrorLedStatus, 0, sizeof(LedStatus_t));

  CloseAlarmBreathingLight();
  SetEventLedPinLevel(false);
  SetAlarmLedPinLevel(false);
}

void EventLedTaskCallback(void)
{
  uint16_t NextWakeupTime = 0;

  switch (EventLedStatus.Status)
  {
  case LED_HINT_FLASHES:
  {
    switch (EventLedStatus.Mode)
    {
    case LED_HINT_SET_PARAMETER_SUCCESS:
      NextWakeupTime = ((EventLedStatus.Count % LED_FLASH_SET_PARAMETER_SUCCESS_COUNT) == 0) ? STRONG_PROMPTING_FLASHING_PERIOD : WEAK_CUE_FLASHING_PERIOD;
      break;

    case LED_HINT_KEY_OPERATION_SUCCESS:
      NextWakeupTime = (EventLedStatus.Count % LED_FLASH_KEY_OPERATION_SUCCESS_COUNT == 0) ? STRONG_PROMPTING_FLASHING_PERIOD : WEAK_CUE_FLASHING_PERIOD;
      break;

    case LED_HINT_TIME_ERROR:
      NextWakeupTime = STRONG_PROMPTING_FLASHING_PERIOD;
      break;

    case LED_HINT_NORMAL_OPEN_TIGGER:
      NextWakeupTime = ALARM_HINT_FLASHING_PERIOD;
      break;

    default:
      NextWakeupTime = WEAK_CUE_FLASHING_PERIOD;
      break;
    }

    SetEventLedPinLevel(true);
    BasicDelayedStartEventLedTask(NextWakeupTime);

    EventLedStatus.Status = LED_HINT_OFF;
    if (EventLedStatus.Count > 0)
    {
      EventLedStatus.Count--;
    }
  }
  break;

  case LED_HINT_OFF:
  {
    SetEventLedPinLevel(false);

    if (EventLedStatus.Count > 0)
    {
      switch (EventLedStatus.Mode)
      {
      case LED_HINT_SET_PARAMETER_SUCCESS:
        NextWakeupTime = ((EventLedStatus.Count % 3) == 2) ? STRONG_PROMPTING_FLASHING_PERIOD : WEAK_CUE_FLASHING_PERIOD;
        break;

      default:
        NextWakeupTime = MEDIUM_FLASHING_PERIOD;
        break;
      }

      EventLedStatus.Status = LED_HINT_FLASHES;
      BasicDelayedStartEventLedTask(NextWakeupTime);
    }
    else
    {
      EventLedStatus.Mode = LED_HINT_IDLE;
    }
  }
  break;

  case LED_HINT_NORMAILON:
  {
    SetEventLedPinLevel(true);
  }
  break;

  default:
    break;
  }
}

void ErrorLedTaskCallback(void)
{
  uint16_t NextWakeupTime = 0;

  switch (ErrorLedStatus.Status)
  {
  case LED_HINT_FLASHES:
  {
    switch (ErrorLedStatus.Mode)
    {
    case LED_HINT_DECICE_SELF_TEST_ERROR:
      NextWakeupTime = (ErrorLedStatus.Count == 1) ? LONG_DELAY_TIME : WEAK_CUE_FLASHING_PERIOD;
      break;

    case LED_HINT_DEVICE_INTO_STANDBY_MODE:
      NextWakeupTime = WEAK_CUE_FLASHING_PERIOD;
      break;

    case LED_HINT_LOCKED_TIGGER:
    case LED_HINT_NORMAL_OPEN_TIGGER:
    case LED_HINT_DEVICE_LOCKED_STATE:
      NextWakeupTime = ALARM_HINT_FLASHING_PERIOD;
      break;

    case LED_HINT_SYSTEM_LOCKED:
      NextWakeupTime = LONG_DELAY_TIME;
      break;

    default:
      NextWakeupTime = (ErrorLedStatus.Count == 1) ? STRONG_PROMPTING_FLASHING_PERIOD : WEAK_CUE_FLASHING_PERIOD;
      break;
    }

    SetAlarmLedPinLevel(true);
    BasicDelayedStartAlarmLedTask(NextWakeupTime);

    ErrorLedStatus.Status = LED_HINT_OFF;
    if (ErrorLedStatus.Count > 0)
    {
      ErrorLedStatus.Count--;
    }
  }
  break;

  case LED_HINT_OFF:
  {
    SetAlarmLedPinLevel(false);

    if (ErrorLedStatus.Count > 0)
    {
      ErrorLedStatus.Status = LED_HINT_FLASHES;

      switch (ErrorLedStatus.Mode)
      {
      case LED_HINT_ANTI_BREAKING_ALARM_TIGGER:
        NextWakeupTime = STRONG_PROMPTING_FLASHING_PERIOD;
        break;

      case LED_HINT_CONNECT_TEST:
        NextWakeupTime = ((ErrorLedStatus.Count % 5) == 0) ? STRONG_PROMPTING_FLASHING_PERIOD : MEDIUM_FLASHING_PERIOD;
        break;

      case LED_HINT_DEVICE_INITIALIZING:
        NextWakeupTime = ((ErrorLedStatus.Count % 4) == 0) ? STRONG_PROMPTING_FLASHING_PERIOD : MEDIUM_FLASHING_PERIOD;
        break;

      case LED_HINT_FALSE_LOCK_TIGGER:
        NextWakeupTime = ((ErrorLedStatus.Count % 3) == 0) ? STRONG_PROMPTING_FLASHING_PERIOD : MEDIUM_FLASHING_PERIOD;
        break;

      case LED_HINT_LOW_POWER:
        NextWakeupTime = ((ErrorLedStatus.Count % 2) == 0) ? STRONG_PROMPTING_FLASHING_PERIOD : MEDIUM_FLASHING_PERIOD;
        break;

      default:
        NextWakeupTime = MEDIUM_FLASHING_PERIOD;
        break;
      }

      BasicDelayedStartAlarmLedTask(NextWakeupTime);
    }
    else
    {
      CloseAlarmBreathingLight();
      ErrorLedStatus.Mode = LED_HINT_IDLE;
    }
  }
  break;

  case LED_HINT_BREATHING_MODE:
  {
    if (BreathingLight.HintStatus == false)
    {
      BreathingLight.DutyCycle += BREATHING_LIGHT_INCREASING_VALUE;
      if (BreathingLight.DutyCycle >= 100)
      {
        BreathingLight.HintStatus = true;
      }
    }
    else
    {
      BreathingLight.DutyCycle -= BREATHING_LIGHT_INCREASING_VALUE;
      if (BreathingLight.DutyCycle == 0)
      {
        BreathingLight.HintStatus = false;
      }
    }

    switch (ErrorLedStatus.Mode)
    {
    case LED_HINT_DEVICE_SELF_TEST:
      NextWakeupTime = (uint8_t)(BREATHING_LIGHT_FLASHING_PERIOD / 2);
      break;

    case LED_HINT_START_SAFETY_MODULE_AUTHENTICATE:
      NextWakeupTime = (uint8_t)(BREATHING_LIGHT_FLASHING_PERIOD / 5);
      break;

    default:
      NextWakeupTime = BREATHING_LIGHT_FLASHING_PERIOD;
      break;
    }

    UpdateAlarmBreathingLightDutyCycle(BreathingLight.DutyCycle);
    BasicDelayedStartAlarmLedTask(NextWakeupTime);
  }
  break;

  default:
    break;
  }
}

bool CheckIfTheIndicatorLightIsOn(void)
{
  if (ErrorLedStatus.Mode == LED_HINT_IDLE)
  {
    if (EventLedStatus.Mode == LED_HINT_IDLE)
      return false;
  }

  return true;
}

void LedBoardInitialisation(void)
{
  EventLedPinConfiguration();
  AlarmLedPinConfiguration();
}
